from typing import List
from .Class_SVDObject import SVDObject
from .Class_EnumeratedValue import EnumeratedValue
from .Class_EnumeratedValues import EnumeratedValues
from .Class_Field import Field
from .Class_Register import Register

class Peripheral(SVDObject):
    def __init__(self, name: str = "",description: str = "", headerStructName: str = "",derivedFrom: str = "",groupName: str = "", baseAddress: str = "", interrupt = [], offset: str = "", size: str = "",father:str = ""):
        super().__init__(name)
        self.type = "peripheral"
        self.headerStructName = headerStructName
        self.derivedFrom = derivedFrom
        self.father = father
        self.description = description
        self.baseAddress = baseAddress
        self.offset = offset
        self.size = size
        self.groupName = groupName
        self.interrupt = interrupt
        self.registers :List[Register] = []  
    
    def __repr__(self):
        return (f"Peripheral(name={self.name}, father={self.father}, description={self.description},"
                f"description={self.description},headerStructName={self.headerStructName},groupName={self.groupName}, "
                f"baseAddress={self.baseAddress}, interrupt={self.interrupt}, "
                f"offset={self.offset}, size={self.size})")
        
    def SetBaseAddress(self, baseAddress: str) -> None:
        self.baseAddress = baseAddress
    
    def SetDerivedFrom(self, derivedFrom: str) -> None:
        self.derivedFrom = derivedFrom
    
    def SetHeaderStructName(self, headerStructName: str) -> None:
        self.headerStructName = headerStructName    

    def AppendInterrupt(self, interrupt) -> None:
        if self.interrupt == None :
            self.interrupt = []
        self.interrupt.append(interrupt)
    
    def SetOffset(self, offset: str) -> None:
        self.offset = offset
    def SetSize(self, size: str) -> None:
        self.size = size
    def SetSize(self, groupName: str) -> None:
        self.groupName = groupName
        
    def SetFather(self, father: str):
        self.father = father
        # "registers" 这个属性在调试xlsx过程中可能不存在，脚本中会被删除
        if self.derivedFrom == "" and hasattr(self,"registers"): 
            for reg in self.registers:
                reg.SetFather(self.myself())
        else :
            pass
    
    def SetDescription(self, description: str):
        self.description = description

    def toStringOfAddressBlock(self, tablevel) -> str:
        xml_output = (
            f"{self.TabsString(tablevel)}<addressBlock>\n"
            f"{self.TabsString(tablevel + 1)}<offset>{self.offset}</offset>\n"
            f"{self.TabsString(tablevel + 1)}<size>{self.size}</size>\n"
            f"{self.TabsString(tablevel + 1)}<usage>registers</usage>\n"
            f"{self.TabsString(tablevel)}</addressBlock>\n"
        )
        return xml_output
        
    def toStringOfInterrupt(self, tablevel) -> str:
        xml_output = ""
        for thisint in self.interrupt:
            xml_output.append(f"{self.TabsString(tablevel)}<interrupt>\n")
            xml_output.append(f"{self.TabsString(tablevel + 1)}<name>{thisint["int_name"]}</name>\n")
            xml_output.append(f"{self.TabsString(tablevel + 1)}<value>{thisint["interrupt"]}</value>\n")
            if thisint["int_description"] != "":
                xml_output.append(f"{self.TabsString(tablevel + 1)}<description>{thisint["int_description"]}</description>\n")            
            xml_output.append(f"{self.TabsString(tablevel)}</interrupt>\n")
        return xml_output
    
    def AddRegister(self, register):
        register.SetFather(self.myself())
        self.registers.append(register)

    def ValidCheck(self):        
        errcnt = super().ValidCheck()
        # "registers" 这个属性在调试xlsx过程中可能不存在，脚本中会被删除
        if self.derivedFrom == "" and hasattr(self,"registers"): 
            for reg in self.registers:
                errcnt += reg.ValidCheck();
        return errcnt
    
    def InterruptReshape(self):
        int_index = 1
        if self.interrupt != None:
            # 先处理int_name
            if self.interrupt.__len__() == 1 and (self.interrupt[0]["int_name"] == None or self.interrupt[0]["int_name"] == ""):
                self.interrupt[0]["int_name"] = self.name
            else :                
                for thisint in self.interrupt:                    
                    if ("int_name" not in thisint) or (thisint["int_name"] == None) or (thisint["int_name"] == ""):
                        thisint["int_name"] = self.name + "_" + str(int_index)
                    int_index = int_index + 1
            # 处理int号和description
            for thisint in self.interrupt:                    
                if ("interrupt" not in thisint) or (thisint["interrupt"] == None) or (thisint["interrupt"] == ""):
                    thisint["interrupt"] = 1000            
                if ("int_description" not in thisint) or (thisint["int_description"] == None):
                    thisint["int_description"] = ""
        else :
            self.interrupt = []
            

                

        
    def toString(self, tablevel) -> str:
        self.InterruptReshape()
        if self.derivedFrom :            
            xml_output = f"{self.TabsString(tablevel)}<peripheral derivedFrom=\"{self.derivedFrom}\"><!--{self.name}-->\n"        
            xml_output += f"{self.TabsString(tablevel+1)}<name>{self.name}</name>\n"
            if self.groupName :
                xml_output += f"{self.TabsString(tablevel+1)}<groupName>{self.groupName}</groupName>\n"
            xml_output += f"{self.TabsString(tablevel + 1)}<baseAddress>{self.baseAddress}</baseAddress>\n"  
            xml_output += self.toStringOfInterrupt(tablevel + 1)
            xml_output += f"{self.TabsString(tablevel)}</peripheral>\n"
            
        else :
            xml_output = f"{self.TabsString(tablevel)}<peripheral><!--{self.name}-->\n"        
            xml_output += f"{self.TabsString(tablevel+1)}<name>{self.name}</name>\n"
            if self.headerStructName:
                xml_output += f"{self.TabsString(tablevel+1)}<headerStructName>{self.headerStructName}</headerStructName>\n"
            if self.groupName :
                xml_output += f"{self.TabsString(tablevel+1)}<groupName>{self.groupName}</groupName>\n"
            
            if self.description :
                xml_output += f"{self.TabsString(tablevel + 1)}<description>{self.description}</description>\n"
                
            xml_output += f"{self.TabsString(tablevel + 1)}<baseAddress>{self.baseAddress}</baseAddress>\n"
        
            xml_output += self.toStringOfAddressBlock(tablevel + 1)
            
            xml_output += self.toStringOfInterrupt(tablevel + 1)

            # 添加寄存器
            xml_output += f"{self.TabsString(tablevel + 1)}<registers>\n"
            for register in self.registers:
                xml_output += register.toString(tablevel + 2)
            xml_output += f"{self.TabsString(tablevel + 1)}</registers>\n"

            xml_output += f"{self.TabsString(tablevel)}</peripheral>\n"
        return xml_output
    
    def toXmlObj(self, xmlfather):
        self.InterruptReshape()
        doc = xmlfather.ownerDocument
        
        if self.derivedFrom:
            peripheral_element = doc.createElement('peripheral')
            peripheral_element.setAttribute('derivedFrom', self.derivedFrom)
        else:
            peripheral_element = doc.createElement('peripheral')
        
        name_element = doc.createElement('name')
        name_text = doc.createTextNode(self.name)
        name_element.appendChild(name_text)
        peripheral_element.appendChild(name_element)
        
        if self.groupName:
            group_name_element = doc.createElement('groupName')
            group_name_text = doc.createTextNode(self.groupName)
            group_name_element.appendChild(group_name_text)
            peripheral_element.appendChild(group_name_element)
        
        if not self.derivedFrom and self.headerStructName:
            header_struct_name_element = doc.createElement('headerStructName')
            header_struct_name_text = doc.createTextNode(self.headerStructName)
            header_struct_name_element.appendChild(header_struct_name_text)
            peripheral_element.appendChild(header_struct_name_element)
        
        if not self.derivedFrom and self.description:
            description_element = doc.createElement('description')
            description_text = doc.createTextNode(self.description)
            description_element.appendChild(description_text)
            peripheral_element.appendChild(description_element)
        
        base_address_element = doc.createElement('baseAddress')
        base_address_text = doc.createTextNode(self.baseAddress)
        base_address_element.appendChild(base_address_text)
        peripheral_element.appendChild(base_address_element)
        
        if not self.derivedFrom:
            address_block_element = doc.createElement('addressBlock')
            offset_element = doc.createElement('offset')
            offset_text = doc.createTextNode(self.offset)
            offset_element.appendChild(offset_text)
            address_block_element.appendChild(offset_element)
            
            size_element = doc.createElement('size')
            size_text = doc.createTextNode(self.size)
            size_element.appendChild(size_text)
            address_block_element.appendChild(size_element)
            
            usage_element = doc.createElement('usage')
            usage_text = doc.createTextNode('registers')
            usage_element.appendChild(usage_text)
            address_block_element.appendChild(usage_element)
            
            peripheral_element.appendChild(address_block_element)
        
        if self.interrupt:
            for thisint in self.interrupt:
                interrupt_element = doc.createElement('interrupt')
                
                interrupt_name_element = doc.createElement('name')
                interrupt_name_text = doc.createTextNode(thisint["int_name"])
                interrupt_name_element.appendChild(interrupt_name_text)
                interrupt_element.appendChild(interrupt_name_element)
                
                interrupt_value_element = doc.createElement('value')
                interrupt_value_text = doc.createTextNode(str(thisint["interrupt"]))
                interrupt_value_element.appendChild(interrupt_value_text)
                interrupt_element.appendChild(interrupt_value_element)
                
                if thisint["int_description"] != "":
                    interrupt_spec_element = doc.createElement('description')
                    interrupt_spec_text = doc.createTextNode(thisint["int_description"])
                    interrupt_spec_element.appendChild(interrupt_spec_text)
                    interrupt_element.appendChild(interrupt_spec_element)
                    
                peripheral_element.appendChild(interrupt_element)
        
        # "registers" 这个属性在调试xlsx过程中可能不存在，脚本中会被删除
        if not self.derivedFrom and hasattr(self,"registers"):
            registers_element = doc.createElement('registers')
            for register in self.registers:
                register.toXmlObj(registers_element)
            peripheral_element.appendChild(registers_element)
        
        xmlfather.appendChild(peripheral_element)

    @staticmethod
    def GetTestObject():
        peripheral = Peripheral(
            name="LIN",
            description="LIN FlexD",
            groupName="LIN",
            baseAddress="0x4000A000"
        )
        reg = Register.GetTestObject()
        peripheral.AddRegister(reg)
        reg = Register.GetTestObject()
        peripheral.AddRegister(reg)
        return peripheral

    @staticmethod
    def TestString():
        testObject = Peripheral.GetTestObject()
        print(testObject.toString(2))